package network

import (
	"gitee.com/amoyx/cloud-provider/pkg/cloud/tencent/models"
	tclb "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb/v20180317"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
	"strings"
)

type CLBGreeter interface {
	CLB(region string) CLBInterface
}

type CLBInterface interface {
	CreateBandWidthInstance(args models.CLBRequest) (result models.CreateResponseParams, err error)
	CreateTrafficInstance(args models.CLBRequest) (result models.CreateResponseParams, err error)
	ModifyInstance(id string, name string, maxBandwidth int64, internetChargeType string) error
	DeleteInstance(id string) (err error)
	Get(id string) (result models.CLBResponse, err error)
	ListByName(name string) (list []models.CLBResponse, err error)
	ListByLBType(lbType string) (list []models.CLBResponse, err error)
}

type clb struct {
	network *Network
	region  string
	client  *tclb.Client
}

func newCLB(network *Network, region string) CLBInterface {
	v := &clb{
		network: network,
		region:  region,
	}
	cpf := profile.NewClientProfile()
	cpf.HttpProfile.Endpoint = string(VpcEndPoint)
	client, _ := tclb.NewClient(v.network.Credential(), v.region, cpf)
	v.client = client
	return v
}

// CreateBandWidthInstance 创建按带宽付费CLB实例
func (c *clb) CreateBandWidthInstance(args models.CLBRequest) (result models.CreateResponseParams, err error) {
	return c.create("BANDWIDTH_POSTPAID_BY_HOUR", args)
}

// CreateTrafficInstance 创建按流量付费CLB实例
func (c *clb) CreateTrafficInstance(args models.CLBRequest) (result models.CreateResponseParams, err error) {
	return c.create("TRAFFIC_POSTPAID_BY_HOUR", args)
}

func (c *clb) create(chargeType string, args models.CLBRequest) (result models.CreateResponseParams, err error) {
	request := tclb.NewCreateLoadBalancerRequest()
	request.LoadBalancerType = common.StringPtr(args.LoadBalancerType)
	request.Forward = common.Int64Ptr(1)
	request.LoadBalancerName = common.StringPtr(args.LoadBalancerName)
	request.VpcId = common.StringPtr(args.VpcId)
	request.SubnetId = common.StringPtr(args.SubnetId)
	request.Number = common.Uint64Ptr(1)
	if args.LoadBalancerType == "OPEN" {
		request.AddressIPVersion = common.StringPtr("IPV4")
		request.InternetAccessible = &tclb.InternetAccessible{
			InternetChargeType:      common.StringPtr(chargeType),
			InternetMaxBandwidthOut: common.Int64Ptr(args.InternetMaxBandwidthOut),
		}
		if strings.TrimSpace(args.ZoneId) != "" {
			request.ZoneId = common.StringPtr(args.ZoneId)
		}
	}
	response, err := c.client.CreateLoadBalancer(request)
	if err != nil {
		return
	}
	res := response.Response
	result.RequestId = *res.RequestId
	for _, id := range res.LoadBalancerIds {
		result.InstanceSet = append(result.InstanceSet, *id)
	}
	return
}

// ModifyInstance 修改CLB实例配置，只能修改实例名称，带宽大小，付费类型
func (c *clb) ModifyInstance(id string, name string, maxBandwidth int64, internetChargeType string) error {
	request := tclb.NewModifyLoadBalancerAttributesRequest()
	request.LoadBalancerId = common.StringPtr(id)
	if strings.TrimSpace(name) != "" {
		request.LoadBalancerName = common.StringPtr(name)
	}
	if instance, err := c.Get(id); err == nil && instance.LoadBalancerType == "OPEN" {
		chargeInfo := &tclb.InternetAccessible{}
		if strings.TrimSpace(internetChargeType) != "" {
			chargeInfo.InternetChargeType = common.StringPtr(internetChargeType)
		}
		if maxBandwidth > 0 {
			chargeInfo.InternetMaxBandwidthOut = common.Int64Ptr(maxBandwidth)
		}
		request.InternetChargeInfo = chargeInfo
	}
	_, err := c.client.ModifyLoadBalancerAttributes(request)
	return err
}

func (c *clb) DeleteInstance(id string) (err error) {
	request := tclb.NewDeleteLoadBalancerRequest()
	request.LoadBalancerIds = common.StringPtrs([]string{id})
	_, err = c.client.DeleteLoadBalancer(request)
	return
}

func (c *clb) Get(id string) (result models.CLBResponse, err error) {
	list, err := c.query(id, "", "")
	if len(list) > 0 {
		result = list[0]
	}
	return
}

func (c *clb) ListByName(name string) (list []models.CLBResponse, err error) {
	return c.query("", "", name)
}

func (c *clb) ListByLBType(lbType string) (list []models.CLBResponse, err error) {
	return c.query("", lbType, "")
}

func (c *clb) query(id string, lbType string, name string) (list []models.CLBResponse, err error) {
	request := tclb.NewDescribeLoadBalancersRequest()
	if strings.TrimSpace(id) != "" {
		request.LoadBalancerIds = common.StringPtrs([]string{id})
	}
	if strings.TrimSpace(lbType) != "" {
		request.LoadBalancerType = common.StringPtr(lbType)
	}
	if strings.TrimSpace(name) != "" {
		request.LoadBalancerName = common.StringPtr(name)
	}
	request.Offset = common.Int64Ptr(0)
	request.Limit = common.Int64Ptr(100)
	response, err := c.client.DescribeLoadBalancers(request)
	if err != nil {
		return
	}
	for _, row := range response.Response.LoadBalancerSet {
		list = append(list, models.CLBResponse{
			LoadBalancerId:           *row.LoadBalancerId,
			LoadBalancerName:         *row.LoadBalancerName,
			LoadBalancerType:         *row.LoadBalancerType,
			Forward:                  *row.Forward,
			Status:                   *row.Status,
			CreateTime:               *row.CreateTime,
			StatusTime:               *row.StatusTime,
			VpcId:                    *row.VpcId,
			SubnetId:                 *row.SubnetId,
			AddressIPVersion:         *row.AddressIPVersion,
			IsolatedTime:             *row.IsolatedTime,
			ExpireTime:               *row.ExpireTime,
			ChargeType:               *row.ChargeType,
			LoadBalancerPassToTarget: *row.LoadBalancerPassToTarget,
			SlaType:                  *row.SlaType,
			IsBlock:                  *row.IsBlock,
			IsBlockTime:              *row.IsBlockTime,
		})
	}
	return
}
